use model_graph_types::{
    database::DatabaseType,
    modeling::{AttributeValueConvertor, MetaConnector, Value},
};

use crate::modeling_connector::SimpleMetaConnector;

#[derive(Debug, Default)]
pub struct SimpleAttributeValueConvertor {}

#[async_trait::async_trait]
impl AttributeValueConvertor for SimpleAttributeValueConvertor {
    async fn get_attribute_value(
        &self,
        class_identifier: &String,
        name: &String,
        value: &Value,
    ) -> anyhow::Result<Value> {
        //
        let class = SimpleMetaConnector::default()
            .get_class(class_identifier)
            .await?
            .attribute(name)?;

        let attribute_type = class.data_type;

        Ok(value.convert(&attribute_type)?)
    }

    async fn get_attribute_values(
        &self,
        class_identifier: &String,
        name: &String,
        values: &Vec<Value>,
    ) -> anyhow::Result<Vec<Value>> {
        //
        let class = SimpleMetaConnector::default()
            .get_class(class_identifier)
            .await?
            .attribute(name)?;

        let attribute_type = class.data_type;
        let mut res = vec![];

        for v in values {
            res.push(v.convert(&attribute_type)?);
        }
        Ok(res)
    }

    async fn get_persistence_value(
        &self,
        class_identifier: &String,
        name: &String,
        value: &Value,
        database_type: Option<DatabaseType>,
    ) -> anyhow::Result<Value> {
        let class_attribute = SimpleMetaConnector::default()
            .get_class(class_identifier)
            .await?
            .attribute(name)?;
        let attribute_type = &class_attribute.data_type;

        let storage_type = if let Some(t) = &class_attribute.storage_type {
            t
        } else {
            attribute_type
        };
        //
        tracing::debug!("{}--{:?}", attribute_type, value);
        Ok(value.convert(&attribute_type)?.convert(&storage_type)?)
    }
    async fn get_persistence_values(
        &self,
        class_identifier: &String,
        name: &String,
        values: &Vec<Value>,
        database_type: Option<DatabaseType>,
    ) -> anyhow::Result<Vec<Value>> {
        let class_attribute = SimpleMetaConnector::default()
            .get_class(class_identifier)
            .await?
            .attribute(name)?;
        let attribute_type = &class_attribute.data_type;

        let storage_type = if let Some(t) = &class_attribute.storage_type {
            t
        } else {
            attribute_type
        };
        let mut res = vec![];

        for v in values {
            res.push(v.convert(&attribute_type)?.convert(&storage_type)?);
        }
        Ok(res)
    }
}
